#include "h264_one_frame_get.h"

//int h264_buffer_size = 600 * 1024;
//unsigned char h264_buffer[ 600 * 1024]; 

int h264_one_frame_get_init(H264FileSource *file_sourece, long buffer_length){
    file_sourece->bufSize = ((buffer_length + 500) % 1024) * 1024;//h264_buffer_size //buffer_size 500K~1024K
    file_sourece->buffer = (unsigned char *)malloc(file_sourece->bufSize);//h264_buffer
    if(file_sourece->buffer == NULL)
    {
        printf("h264_one_frame_get_init  malloc buffer error \n");
        return -1;
    }
    file_sourece->readLen = 1024;
    file_sourece->bufLen = 0;
    file_sourece->curFrameIdx = 0;
    file_sourece->curFrameAddr = 0;
    file_sourece->nextFrameAddr = 0;
    file_sourece->findFirstFrame = 0;
    file_sourece->num = 0;
    file_sourece->find_flag = 0;
	return 1;
}

int h264_one_frame_get_process( H264FileSource *file_sourece, 
                                char *src_buffer, int src_len,
                                char * dst_buffer, int *buffer_length)
{

    H264FileSource *pFileSource = file_sourece;

//	printf("file:%s line:%d\n",__FILE__,__LINE__);

    if( pFileSource->bufLen + src_len > pFileSource->bufSize)
    {
        pFileSource->bufLen = 0;
        memset(pFileSource->buffer,0x00,pFileSource->bufSize);
        pFileSource->nextFrameAddr = 0;
        pFileSource->curFrameAddr = 0; 
        pFileSource->find_flag = 0;
        pFileSource->num = 0;
        memcpy(pFileSource->buffer,src_buffer,src_len);
        pFileSource->bufLen += src_len;
        printf("h264_one_frame_get_process buffer is full!\n");
        //data full; clear it; restart process
    }
    else
    {
        memcpy(pFileSource->buffer + pFileSource->bufLen,src_buffer,src_len);
        pFileSource->bufLen += src_len;
        //extraction data
    }
    // printf("pFileSource->nextFrameAddr = %d,pFileSource->bufLen= %d,src = %d\n",
    //         pFileSource->nextFrameAddr,pFileSource->bufLen,src_len);

    //if search to the last exit
    if(pFileSource->nextFrameAddr >= pFileSource->bufLen-6){
		file_sourece->find_flag = 2;
		  return file_sourece->find_flag;
    }

    while (pFileSource->nextFrameAddr < pFileSource->bufLen-6)
    {
            //printf("%x\n", pFileSource->buffer[pFileSource->nextFrameAddr]);
			//head of infomation processing;
            if ( pFileSource->buffer[pFileSource->nextFrameAddr+0] == 0x00 &&
                 pFileSource->buffer[pFileSource->nextFrameAddr+1] == 0x00 &&
                 pFileSource->buffer[pFileSource->nextFrameAddr+2] == 0x00 &&
                 pFileSource->buffer[pFileSource->nextFrameAddr+3] == 0x01) 
            {
            //    printf("find a frame start\n");
                unsigned char nalu_unit_type = pFileSource->buffer[pFileSource->nextFrameAddr+4] & 0x1F;
            //    printf(" nalu_unit_type = %d\n",nalu_unit_type);
                //encode type
                unsigned char first_mb_in_slice = pFileSource->buffer[pFileSource->nextFrameAddr+5] & 0x80;

                if(pFileSource->findFirstFrame == 0)
                {
                    //printf("1--%d\n",pFileSource->nextFrameAddr);
                    pFileSource->curFrameAddr = pFileSource->nextFrameAddr;
                    pFileSource->findFirstFrame = 1;
                    //ERR(" pFileSource->nextFrameAddr = %d\n",pFileSource->nextFrameAddr);
                }
#if 0
            if( nalu_unit_type == 9)
            {
                 num ++;
                 if(  num  == 2)
                 {
                     flag = 1;
                     break;
                 }
            }
#endif

                //ERR("curnum = %d,nextframenum = %d\n",pFileSource->curFrameAddr,pFileSource->nextFrameAddr);
                if (nalu_unit_type >= 1 && nalu_unit_type <= 5) 
                {
                    if (first_mb_in_slice == 0x80) 
                    {
                        //printf("2--%d\n",pFileSource->nextFrameAddr);
                        file_sourece->num ++;
                    //    printf("find the first frame\n");
                    }
                    if (file_sourece->num == 2) 
                    {
                        file_sourece->find_flag = 1;
                    //    printf("2--%ld\n",pFileSource->nextFrameAddr);
                        break;
                    }
                }
                else
                {
                    if (file_sourece->num == 1) {
                    //    printf("3--%ld\n",pFileSource->nextFrameAddr);
                        file_sourece->find_flag = 1;
                        break;
                    }
                }       
            }

            pFileSource->nextFrameAddr++;
            //printf("4--%d\n",pFileSource->nextFrameAddr);
    }
        
    if (file_sourece->find_flag == 1)
    {
        //printf("5-- %d--%d\n",pFileSource->nextFrameAddr , pFileSource->curFrameAddr);
        *buffer_length = pFileSource->nextFrameAddr - pFileSource->curFrameAddr;
        //*buffer_length = pFileSource->nextFrameAddr;
        memcpy(dst_buffer, pFileSource->buffer +pFileSource->curFrameAddr, *buffer_length);
        //printf("memcpy buffer_lenger = %d\n",*buffer_length);
        memcpy(pFileSource->buffer, pFileSource->buffer + pFileSource->nextFrameAddr, pFileSource->bufLen - pFileSource->nextFrameAddr );
        pFileSource->bufLen = pFileSource->bufLen - pFileSource->nextFrameAddr;
        pFileSource->nextFrameAddr = 0;
        pFileSource->findFirstFrame = 0;
        file_sourece->find_flag = 0;
        file_sourece->num = 0;
    }
    else
    {
        *buffer_length = 0;
    }

    return file_sourece->find_flag;
}


int h264_one_frame_get_deinit(H264FileSource *file_sourece){
	free(file_sourece->buffer);
	return 1;
}
